import { BadRequestException, CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common'
import { JwtService } from '@nestjs/jwt'
import { ConfigService } from '@nestjs/config'
import { Request } from 'express'
import { Reflector } from '@nestjs/core'

@Injectable()
export class PublicGuard implements CanActivate {
  constructor(
    private readonly jwtService: JwtService,
    private readonly config: ConfigService,
    private readonly reflector: Reflector
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const isPublic = this.reflector.getAllAndOverride<boolean>('isPublic', [context.getHandler(), context.getClass()])
    if (isPublic) return true

    const request = context.switchToHttp().getRequest() // 获取请求对象
    const token = this.extractTokenFromHeader(request) // 从请求头中提取token
    if (!token) throw new BadRequestException('token 缺失') // 如果没有token，抛出验证不通过异常

    try {
      const payload = await this.jwtService.verifyAsync(token, {
        secret: this.config.get<string>('JWT_SECRET') // 使用JWT_SECRET解析token
      })
      request['user'] = payload // 将解析后的用户信息存储在请求对象中
    } catch {
      throw new UnauthorizedException('token 校验失败') // token验证失败，抛出异常
    }
    return true // 身份验证通过
  }

  private extractTokenFromHeader(request: Request): string | undefined {
    const [type, token] = request.headers.authorization?.split(' ') ?? [] // 从Authorization头中提取token
    return type === 'Bearer' ? token : undefined // 如果是Bearer类型的token，返回token；否则返回undefined
  }
}
